/*
* Copyright (C) 2012  lidp.
*
* Contact: lidp <openser@yeah.org>
*	
* This file is part of Open Source Peasant Framework.
*
* Peasant is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*	
* You should have received a copy of the GNU General Public License
* along with Peasant.
*
*/

/**@file pst_thread.c
 * @brief . thread relitate utilities
 *
 */

#include "pst_thread.h"
#include "pst_logger.h"
#include "pst_mem.h"

#if PST_UNDER_WINDOWS
#include <windows.h>
#else
#include <pthread.h>
 #endif

int pst_thread_create(void** id, void*(*start_runtine), void *data)
{
#if PST_UNDER_WINDOWS
	DWORD Id;
	*((HANDLE*)id) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_runtine, data, 0, &Id);
	return *((HANDLE*)id)  ? 0 : -1;
#else
	*id = pts_calloc(1,sizeof(pthread_t));
	return  pthread_create((pthread_t*)*id, 0, start_runtine, data);
#endif
}

int pst_thread_join(void**id)
{
	int ret;

	if(!id) {
		pst_log(LOG_ERROR, "null thread id!\n");
		return -1;
	}

	if(!*id) {
		pst_log(LOGGER_ERROR, "Invalid thread id !\n");
		return -1;
	}
	
#if PST_UNDER_WINDOWS
	ret = (WaitForSingleObject(*((HANDLE*)id), INFINITE)
	if( ret == 0) {
		CloseHandle(*((HANDLE*)id));
		*id = PST_NULL;
	}
#else
	if((ret = pthread_join((*(pthread_t*)*id), 0)) == 0) {
		pst_free(id);
	}
#endif

	return ret;
}

/*
 *@ sleep in millsec
 */ 
void pst_thread_sleep(uint64_t millsec)
{
#if PST_UNDER_WINDOWS
	Sleep((DWORD)millsec);
#else
	struct timespec spec;
	spec.tv_sec = (long)(millsec/1000);
	spec.tv_nsec = (millsec%1000)* 1000000;
	nanosleep(&spec, 0);
#endif
}